package com.cyys.common.utils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;

public class AESUtil {
    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "AES";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS5Padding";
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    private static final String CHARSET = "utf-8";

    /*
        小程序接口密匙
     */
    private static final String WX_AES_KEY="TTsGZjjeTkOT7qJXV1F5NLWBs3oBP0tb";
    /*
        小程序接口偏移量
     */
    private static final String WX_AES_IV="eaV7axAuA39NOCL8";

    public static final String AES_KEY="UB64crH558RAQcO33kIMtvSnqNq46gUs";
    public static final String COIN="3a310d0842ed4dd1";
    /**
     * AES加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encryptData(String keyStr, String data) throws Exception {
        /**
         * 生成key
         */
        SecretKeySpec key = new SecretKeySpec(MD5Util.calcMD5(keyStr).toLowerCase().getBytes(), ALGORITHM);
        // 创建密码器
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        // 初始化
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return Base64.encodeBase64String(cipher.doFinal(data.getBytes()));
    }

    /**
     * AES加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encryptDataBase(String keyStr, String data) throws Exception {
        /**
         * 生成key
         */
        SecretKeySpec key = new SecretKeySpec(keyStr.getBytes(), ALGORITHM);
        // 创建密码器
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        // 初始化
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return Base64.encodeBase64String(cipher.doFinal(data.getBytes()));
    }

    /**
     * AES解密
     *
     * @param base64Data
     * @return
     * @throws Exception
     */
    public static String decryptData(String keyStr, String base64Data) throws Exception {
        /**
         * 生成key
         */
        SecretKeySpec key = new SecretKeySpec(MD5Util.calcMD5(keyStr).toLowerCase().getBytes(), ALGORITHM);
        Security.addProvider(new BouncyCastleProvider());
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String(cipher.doFinal(Base64.decodeBase64(base64Data)));
    }

    /**
     * AES解密
     *
     * @param base64Data
     * @return
     * @throws Exception
     */
    public static String decryptDataBase(String keyStr, String base64Data) throws Exception {
        /**
         * 生成key
         */
        SecretKeySpec key = new SecretKeySpec(keyStr.getBytes(), ALGORITHM);
        //Security.addProvider(new BouncyCastleProvider());
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String(cipher.doFinal(Base64.decodeBase64(base64Data)));
    }
    /**
     * 获取key & iv
     *
     * @param context
     * @param opmode
     * @return
     * @throws Exception
     */
    public static byte[] createKeyAndIv(byte[] context, int opmode) throws Exception {
        byte[] key = WX_AES_KEY.getBytes(CHARSET);
        byte[] iv = WX_AES_IV.getBytes(CHARSET);
        return cipherFilter(context, opmode, key, iv);
    }

    /**
     * 执行操作
     *
     * @param context
     * @param opmode
     * @param key
     * @param iv
     * @return
     * @throws Exception
     */
    public static byte[] cipherFilter(byte[] context, int opmode, byte[] key, byte[] iv) throws Exception {
        Key secretKeySpec = new SecretKeySpec(key, ALGORITHM);
        AlgorithmParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(opmode, secretKeySpec, ivParameterSpec);
        return cipher.doFinal(context);
    }
    public static  String encryWxApi(String base64Data)throws Exception{
        try {
            byte[] decode = base64Data.getBytes(CHARSET);
            byte[] bytes = createKeyAndIv(decode, Cipher.ENCRYPT_MODE);
            return Base64.encodeBase64String(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static  String decryWxApi(String base64Data)throws Exception{
        try {
            byte[] decode = Base64.decodeBase64(base64Data);
            byte[] bytes = createKeyAndIv(decode, Cipher.DECRYPT_MODE);
            return new String(bytes, CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES 加密
     * @param context
     * @param iv
     * @param key
     * @return
     */
    public static String encryptWithKey(String context,String iv,String key) {
        try {
            byte[] decode = context.getBytes(CHARSET);
            byte[] bytes = createKeyAndIvKey(decode,Cipher.ENCRYPT_MODE,iv,key);
            return Base64.encodeBase64String(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 携带IV的解密方式
     * @param context
     * @return
     */
    public static String decryptWithIVKEY(String context,String iv,String key) {
        try {
            byte[] decode = Base64.decodeBase64(context);
            byte[] bytes = createKeyAndIvKey(decode, Cipher.DECRYPT_MODE,iv,key);
            return new String(bytes, CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取key 自定义iv
     * @param context
     * @param opmode
     * @param iv
     * @return
     * @throws Exception
     */
    public static byte[] createKeyAndIvKey(byte[] context, int opmode,String iv,String key) throws Exception {
        return cipherFilter(context, opmode, key.getBytes(CHARSET), iv.getBytes(CHARSET));
    }

    public static void main(String[] args) throws Exception {
        String text="test";
        String a=AESUtil.encryptWithKey(text,COIN,AES_KEY);
        System.out.println(a);
        System.out.println(AESUtil.decryptWithIVKEY(a,COIN,AES_KEY));
    }
}
